home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / spacewar / mail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-31  |  11.7 KB  |  448 lines

  1. /*
  2.  * Spacewar - mail subsystem
  3.  *
  4.  * Copyright 1984 obo Systems, Inc.
  5.  * Copyright 1984 Dan Rosenblatt
  6.  */
  7.  
  8. #ifndef VMS
  9. #include <sys/types.h>
  10. #include <dbm.h>
  11. #else /* BSD SYSIII SYSV */
  12. #include <types.h>
  13. #include "dbm.h"
  14. #endif /* VMS */
  15. #include <time.h>
  16. #include "spacewar.h"
  17. #include "universe.h"
  18. #include "login.h"
  19. #include "mlbx.h"
  20. #include "plyr.h"
  21.  
  22. #define MAILPROMPT    "player/O(ld)/N(ew)/D(elete)/.(quit)>"
  23.  
  24. struct mstat {
  25.     char    ms_stat;    /* D(isplay) or S(end) */
  26.     short    ms_bgn;        /* display begin */
  27.     short    ms_cur;        /* display current */
  28.     short    ms_end;        /* display end */
  29.     char    ms_towho[8+1];    /* send to player */
  30.     struct mlst *ms_frst;    /* send first line */
  31.     struct mlst *ms_lst;    /* send last line */
  32. };
  33. struct mlst {
  34.     struct mlst *ml_nxt;    /* next mail */
  35.     char    *ml_lin;    /* line of mail */
  36. };
  37.  
  38. static VOID sndmail(),dspmail();
  39. extern char *malloc();
  40.  
  41. mail(plogin)
  42. register struct login *plogin;
  43. {
  44.     register struct mstat *pmstat;
  45.     struct mlbxkey getmbkey;
  46.     struct plyrkey getplkey;
  47.     struct plyr getpldat;
  48.     datum dbmkey,dbmdata;
  49.     int i;
  50.     char buf[80+1],c;
  51.  
  52. #ifdef DEBUG
  53.     DBG("mail(#%d/%s)\n",plogin-loginlst,plogin->ln_name);
  54. #endif
  55.  
  56.     /********************************/
  57.     /* call subtask based on status */
  58.     /********************************/
  59.     if (pmstat = (struct mstat *)plogin->ln_substat)
  60.         switch(pmstat->ms_stat) {
  61.         case 'D':
  62.             dspmail(plogin,pmstat);
  63.             break;
  64.         case 'S':
  65.             sndmail(plogin,pmstat);
  66.             break;
  67.         default:
  68.             perror("mail: unknown ms_stat");
  69.             plogin->ln_stat = NULL;
  70.             plogin->ln_substat = NULL;
  71.             output(plogin,'C',0,PROMPT);
  72.             output(plogin,0,0,0);
  73.             break;
  74.         }
  75.  
  76.     /*******************************************/
  77.     /* no status. figure based on input buffer */
  78.     /*******************************************/
  79.  
  80.     /* nothing - send counts & subtask prompt */
  81.     else if (!plogin->ln_input[0]) {
  82.         /* get player */
  83.         binit((char *)&getplkey,sizeof(getplkey));
  84.         getplkey.pl_plyrkey = PLYR;
  85.         strcpy(getplkey.pl_name,plogin->ln_name);
  86.         dbmkey.dptr = (char *)&getplkey;
  87.         dbmkey.dsize = sizeof(getplkey);
  88.         dbmdata = fetch(dbmkey);
  89.         if (!dbmdata.dptr) {    /* not found? */
  90.             perror("mail: can't find plyr");
  91.             plogin->ln_stat = NULL;
  92.             plogin->ln_substat = NULL;
  93.             output(plogin,'C',0,PROMPT);
  94. #ifdef DEBUG
  95.             VDBG("mail return\n");
  96. #endif
  97.             return;
  98.         }
  99.         bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
  100.  
  101.         sprintf(buf,
  102.         "\nYou have %d line(s) of old mail, %d line(s) of new mail.\n",
  103.         getpldat.pl_seenml - getpldat.pl_frstml + 1,
  104.         getpldat.pl_lstml - getpldat.pl_seenml);
  105.         output(plogin,'C',0,buf);
  106.         output(plogin,'C',0,MAILPROMPT);
  107.         output(plogin,0,0,0);
  108.  
  109.     /* one character - command */
  110.     } else if (!plogin->ln_input[1]) {
  111.  
  112.         /* get player */
  113.         binit((char *)&getplkey,sizeof(getplkey));
  114.         getplkey.pl_plyrkey = PLYR;
  115.         strcpy(getplkey.pl_name,plogin->ln_name);
  116.         dbmkey.dptr = (char *)&getplkey;
  117.         dbmkey.dsize = sizeof(getplkey);
  118.         dbmdata = fetch(dbmkey);
  119.         if (!dbmdata.dptr) {    /* not found? */
  120.         perror("mail: can't find plyr");
  121.         plogin->ln_stat = NULL;
  122.         plogin->ln_substat = NULL;
  123.         output(plogin,'C',0,PROMPT);
  124. #ifdef DEBUG
  125.         VDBG("mail return\n");
  126. #endif
  127.         return;
  128.         }
  129.         bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
  130.  
  131.         switch(c=plogin->ln_input[0]) {
  132.  
  133.         case 'D':    /* delete all seen mail */
  134.         case 'd':
  135.             binit((char *)&getmbkey,sizeof(getmbkey));
  136.             getmbkey.mb_mlbxkey = MLBX;
  137.             strcpy(getmbkey.mb_plyr,plogin->ln_name);
  138.             dbmkey.dptr = (char *)&getmbkey;
  139.             dbmkey.dsize = sizeof(getmbkey);
  140.             i = 0;
  141.             while (getpldat.pl_frstml <= getpldat.pl_seenml) {
  142.             getmbkey.mb_mlbx = getpldat.pl_frstml++;
  143.             if (delete(dbmkey))
  144.                 perror("mail: can't delete mlbx");
  145.             else
  146.                 ++i;
  147.             }
  148.             sprintf(buf,"\nDeleted %d line(s) of mail\n",i);
  149.             output(plogin,'C',0,buf);
  150.  
  151.             /* update plyr */
  152.             dbmkey.dptr = (char *)&getplkey;
  153.             dbmkey.dsize = sizeof(getplkey);
  154.             dbmdata.dptr = (char *)&getpldat;
  155.             dbmdata.dsize = sizeof(getpldat);
  156.             if (store(dbmkey,dbmdata))
  157.             perror("mail: can't update plyr");
  158.  
  159.             /* back to command prompt */
  160.         case '.':    /* quit mail */
  161.             plogin->ln_stat = NULL;
  162.             output(plogin,'C',0,PROMPT);
  163.             output(plogin,0,0,0);
  164.             break;
  165.  
  166.         case 'O':    /* display old mail */
  167.         case 'o':
  168.         case 'N':    /* display new mail */
  169.         case 'n':
  170.             /* allocate subtask status structure */
  171.             if (!(pmstat = (struct mstat *)
  172.             malloc(sizeof(struct mstat)))) {
  173.             perror("mail: out of memory for mstat");
  174.             plogin->ln_stat = NULL;
  175.             output(plogin,'C',0,PROMPT);
  176.             output(plogin,0,0,0);
  177.             break;
  178.             }
  179.  
  180.             /* initialize subtask status structure */
  181.             pmstat->ms_stat = 'D';
  182.             if (c == 'O' || c == 'o') {
  183.             pmstat->ms_bgn = getpldat.pl_frstml;
  184.             pmstat->ms_end = getpldat.pl_seenml;
  185.             } else {
  186.             pmstat->ms_bgn = getpldat.pl_seenml + 1;
  187.             pmstat->ms_end = getpldat.pl_lstml;
  188.             }
  189.             pmstat->ms_cur = pmstat->ms_bgn - 1;
  190.  
  191.             /* save subtask status structure and start subtask */
  192.             plogin->ln_substat = (char *) pmstat;
  193.             dspmail(plogin,pmstat);
  194.             break;
  195.  
  196.         default:
  197.             output(plogin,'C',0,MAILPROMPT);
  198.             output(plogin,0,0,0);
  199.             break;
  200.         }
  201.  
  202.     /* send to player */
  203.     } else {
  204.         /* allocate/initialize subtask status structure */
  205.         if (!(pmstat = (struct mstat *) malloc(sizeof(struct mstat)))) {
  206.             perror("mail: out of memory for mstat");
  207.             plogin->ln_stat = NULL;
  208.             output(plogin,'C',0,PROMPT);
  209.             output(plogin,0,0,0);
  210.         } else {
  211.             pmstat->ms_stat = 'S';
  212.             plogin->ln_input[sizeof(pmstat->ms_towho)-1] = NULL;
  213.             strcpy(pmstat->ms_towho,plogin->ln_input);
  214.             pmstat->ms_frst = pmstat->ms_lst = NULL;
  215.             plogin->ln_substat = (char *) pmstat;
  216.             sndmail(plogin,pmstat);
  217.         }
  218.     }
  219.  
  220. #ifdef DEBUG
  221.     VDBG("mail return\n");
  222. #endif
  223. }
  224.  
  225. static VOID dspmail(plogin,pmstat)
  226. register struct login *plogin;
  227. register struct mstat *pmstat;
  228. {
  229.     struct mlbxkey getmbkey;
  230.     struct plyrkey getplkey;
  231.     struct plyr getpldat;
  232.     datum dbmkey,dbmdata;
  233.     char buf[80+1];
  234.     int nlines=6;
  235.  
  236. #ifdef DEBUG
  237.     DBG("dspmail(#%d/%s,{%d,%d,%d})\n",plogin-loginlst,plogin->ln_name,
  238.     pmstat->ms_bgn,pmstat->ms_cur,pmstat->ms_end);
  239. #endif
  240.  
  241.     /* first time */
  242.     if (pmstat->ms_cur < pmstat->ms_bgn) {
  243.  
  244.         sprintf(buf,"\nThere are %d line(s) of mail\n",
  245.         pmstat->ms_end - pmstat->ms_bgn + 1);
  246.         output(plogin,'C',0,buf);
  247.  
  248.         if (pmstat->ms_end >= pmstat->ms_bgn) {
  249.             sprintf(buf,"Output is in groups of %d lines. ",nlines);
  250.             output(plogin,'C',0,buf);
  251.             output(plogin,'C',0,"Hit return when ready for more.\n");
  252.             output(plogin,'C',0,
  253.             "A single dot (.) on a line by itself terminates Mail.\n\n");
  254.             plogin->ln_iomode = 'm';
  255.         }
  256.     }
  257.  
  258.     /* display a group of lines */
  259.     binit((char *)&getmbkey,sizeof(getmbkey));
  260.     getmbkey.mb_mlbxkey = MLBX;
  261.     strcpy(getmbkey.mb_plyr,plogin->ln_name);
  262.     dbmkey.dptr = (char *)&getmbkey;
  263.     dbmkey.dsize = sizeof(getmbkey);
  264.     while (nlines-- > 0) {
  265.  
  266.         /* terminate or no more - update plyr */
  267.         /* and go back to command level */
  268.         if (!strcmp(plogin->ln_input,".") ||
  269.         ++pmstat->ms_cur > pmstat->ms_end) {
  270.             binit((char *)&getplkey,sizeof(getplkey));
  271.             getplkey.pl_plyrkey = PLYR;
  272.             strcpy(getplkey.pl_name,plogin->ln_name);
  273.             dbmkey.dptr = (char *)&getplkey;
  274.             dbmkey.dsize = sizeof(getplkey);
  275.             dbmdata = fetch(dbmkey);
  276.             if (!dbmdata.dptr)    /* not found? */
  277.                 perror("dspmail: can't find plyr");
  278.             else {
  279.                 bcopy((char *)&getpldat,dbmdata.dptr,
  280.                 sizeof(getpldat));
  281.                 getpldat.pl_seenml =
  282.                     (pmstat->ms_cur < pmstat->ms_end) ?
  283.                     pmstat->ms_cur : pmstat->ms_end;
  284.                 dbmdata.dptr = (char *)&getpldat;
  285.                 dbmdata.dsize = sizeof(getpldat);
  286.                 if (store(dbmkey,dbmdata))
  287.                     perror("dspmail: can't update plyr");
  288.             }
  289.  
  290.             free((char *)pmstat);
  291.             plogin->ln_iomode = NULL;
  292.             plogin->ln_stat = NULL;
  293.             plogin->ln_substat = NULL;
  294.             output(plogin,'C',0,PROMPT);
  295.             break;
  296.  
  297.         /* get and put out the line of mail */
  298.         } else {
  299.             getmbkey.mb_mlbx = pmstat->ms_cur;
  300.             dbmdata = fetch(dbmkey);
  301.             if (!dbmdata.dptr)    /* not found? */
  302.                 perror("dspmail: can't find mlbx");
  303.             else {
  304.                 output(plogin,'C',0,dbmdata.dptr);
  305.                 output(plogin,'C',0,"\n");
  306.             }
  307.         }
  308.     }
  309.  
  310.     output(plogin,0,0,0);
  311. #ifdef DEBUG
  312.     VDBG("dspmail return\n");
  313. #endif
  314. }
  315.  
  316. static VOID sndmail(plogin,pmstat)
  317. register struct login *plogin;
  318. register struct mstat *pmstat;
  319. {
  320.     time_t clock;
  321.     struct mlst *pmlst,*nxtmlst;
  322.     struct plyrkey getplkey;
  323.     struct plyr getpldat;
  324.     struct mlbxkey getmbkey;
  325.     datum dbmkey,dbmdata;
  326.     int mlost=0,nlines;
  327.     struct tm *localtime();
  328.     char *asctime(),*ctime(),buf[80+1];
  329.  
  330. #ifdef DEBUG
  331.     DBG("sndmail(#%d/%s,%s)\n",plogin-loginlst,plogin->ln_name,
  332.     pmstat->ms_towho);
  333. #endif
  334.  
  335.     /* first time or terminate */
  336.     if (!pmstat->ms_frst || !strcmp(plogin->ln_input,".")) {
  337.  
  338.         /* verify existence of recipient */
  339.         binit((char *)&getplkey,sizeof(getplkey));
  340.         getplkey.pl_plyrkey = PLYR;
  341.         strcpy(getplkey.pl_name,pmstat->ms_towho);
  342.         dbmkey.dptr = (char *)&getplkey;
  343.         dbmkey.dsize = sizeof(getplkey);
  344.         dbmdata = fetch(dbmkey);
  345.         if (!dbmdata.dptr) {    /* doesn't exist */
  346.         output(plogin,'C',0,pmstat->ms_towho);
  347.         output(plogin,'C',0," - no such player\n");
  348.         goto terminate;    /* horrendous */
  349.  
  350.         } else if (!pmstat->ms_frst) {    /* first time */
  351.         time(&clock);
  352.         sprintf(plogin->ln_input,"From '%s' on %.24s",plogin->ln_name,
  353. #ifdef VMS
  354.         ctime(&clock));
  355. #else /* BSD SYSIII SYSV */
  356.         asctime(localtime(&clock)));
  357. #endif /* VMS BSD SYSIII SYSV */
  358.         output(plogin,'C',0,
  359.         "Terminate your mail with a single dot (.) on a line by itself.\n\n");
  360.         output(plogin,0,0,0);
  361.  
  362.         } else {    /* terminate */
  363.  
  364.         /* insert mlbx lines */
  365.         bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
  366.         binit((char *)&getmbkey,sizeof(getmbkey));
  367.         getmbkey.mb_mlbxkey = MLBX;
  368.         strcpy(getmbkey.mb_plyr,pmstat->ms_towho);
  369.         dbmkey.dptr = (char *)&getmbkey;
  370.         dbmkey.dsize = sizeof(getmbkey);
  371.         for (nlines=(-1),nxtmlst=pmlst=pmstat->ms_frst;pmlst;
  372.         ++nlines,pmlst=nxtmlst) {
  373.             nxtmlst = nxtmlst->ml_nxt;
  374.             getmbkey.mb_mlbx = ++getpldat.pl_lstml;
  375.             dbmdata.dsize = strlen(dbmdata.dptr=pmlst->ml_lin) + 1;
  376.             if (!mlost && store(dbmkey,dbmdata)) {
  377.             ++mlost;
  378.             output(plogin,'C',0,
  379.             "(sigh) database collision, your mail was lost\n");
  380.             }
  381.             free(pmlst->ml_lin);
  382.             free((char *)pmlst);
  383.         }
  384.  
  385.         /* insert trailer, update recipient */
  386.         if (!mlost) {
  387.             getmbkey.mb_mlbx = ++getpldat.pl_lstml;
  388.             dbmdata.dsize = strlen(dbmdata.dptr=".") + 1;
  389.             if (store(dbmkey,dbmdata)) --getpldat.pl_lstml;
  390.  
  391.             dbmkey.dptr = (char *)&getplkey;
  392.             dbmkey.dsize = sizeof(getplkey);
  393.             dbmdata.dptr = (char *)&getpldat;
  394.             dbmdata.dsize = sizeof(getpldat);
  395.             if (store(dbmkey,dbmdata)) {
  396.             perror("sndmail: can't update plyr");
  397.             output(plogin,'C',0,
  398.             "(sigh) database error, your mail was lost\n");
  399.             } else {
  400.             sprintf(buf,"Sent %d+2 line(s) of mail\n",nlines);
  401.             output(plogin,'C',0,buf);
  402.             }
  403.         }
  404.  
  405.         /* back to command prompt */
  406. terminate:
  407.         free((char *)pmstat);
  408.         plogin->ln_stat = NULL;
  409.         plogin->ln_substat = NULL;
  410.         output(plogin,'C',0,PROMPT);
  411.         output(plogin,0,0,0);
  412. #ifdef DEBUG
  413.         VDBG("sndmail return\n");
  414. #endif
  415.         return;
  416.         }
  417.     }
  418.  
  419.     /*************************/
  420.     /* save the line of mail */
  421.     /*************************/
  422.  
  423.     /* terminate early if no memory */
  424.     if (!(pmlst = (struct mlst *) malloc((unsigned)sizeof(struct mlst))))
  425.         perror("sndmail: out of memory for mlst");
  426.     if (!pmlst || !(pmlst->ml_lin = malloc(strlen(plogin->ln_input)+1))) {
  427.         if (pmlst) perror("sndmail: out of memory for ml_lin");
  428.         strcpy(plogin->ln_input,".");
  429.         sndmail(plogin,pmstat);
  430.  
  431.     /* save text and link in to list */
  432.     } else {
  433.         pmlst->ml_nxt = NULL;
  434.         strcpy(pmlst->ml_lin,plogin->ln_input);
  435.         if (pmstat->ms_frst)
  436.             pmstat->ms_lst->ml_nxt = pmlst;
  437.         else
  438.             pmstat->ms_frst = pmlst;
  439.         pmstat->ms_lst = pmlst;
  440.         output(plogin,'C',0,">");
  441.         output(plogin,0,0,0);
  442.     }
  443.  
  444. #ifdef DEBUG
  445.     VDBG("sndmail return\n");
  446. #endif
  447. }
  448.